package com.boot.persistence.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boot.persistence.condition.ColumnCondition;
import com.boot.persistence.condition.OrderCondition;
import com.boot.persistence.condition.PageCondition;
import com.boot.persistence.condition.range.CategoryCondition;
import com.boot.persistence.condition.range.RangeCondition;
import org.springframework.lang.Nullable;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * @author 霜寒 <1621856595@qq.com>
 * @description QueryCondition 工具类
 * @date 2023/4/6 16:09
 **/

public class QueryConditionHelper {

    public static final int MAX_PAGE_SIZE = 500;

    private QueryConditionHelper() {
    }

    public static <T> Page<T> getPage(PageCondition pageCondition) {
        if (pageCondition != null && pageCondition.isUseful()) {
            return new Page<>(pageCondition.getPageNum(), pageCondition.getPageSize());
        }
        return new Page<>(1, MAX_PAGE_SIZE);
    }

    public static <T> QueryWrapper<T> getOrders(List<OrderCondition> orderConditions, @Nullable QueryWrapper<T> wrapper) {
        wrapper = getWrapper(wrapper);
        if (org.springframework.util.CollectionUtils.isEmpty(orderConditions)) {
            return wrapper;
        }
        for (OrderCondition orderCondition : orderConditions) {
            if (ArrayUtil.isNotEmpty(orderCondition.getColumns()) && orderCondition.getMode() != null) {
                orderCondition.camelToUnderline();
                wrapper.orderBy(true, orderCondition.getMode(), orderCondition.getColumns());
            }
        }
        return wrapper;
    }

    public static <T> QueryWrapper<T> getColumns(ColumnCondition columnCondition, @Nullable QueryWrapper<T> wrapper) {
        wrapper = getWrapper(wrapper);
        if (columnCondition == null) {
            return wrapper;
        }
        wrapper = getRanges(columnCondition.getTimeConditions(), wrapper);
        wrapper = getRanges(columnCondition.getNumberConditions(), wrapper);
        wrapper = getCategories(columnCondition.getCategoryConditions(), wrapper);
        return wrapper;
    }

    public static <S, T> QueryWrapper<T> getRanges(List<RangeCondition<S>> rangeConditions, @Nullable QueryWrapper<T> wrapper) {
        wrapper = getWrapper(wrapper);
        if (org.springframework.util.CollectionUtils.isEmpty(rangeConditions)) {
            return wrapper;
        }
        for (RangeCondition<S> rangeCondition : rangeConditions) {
            if (rangeCondition.getColumn() != null) {
                rangeCondition.camelToUnderline();
                if (rangeCondition.getBegin() != null
                        && rangeCondition.getEnd() != null) {
                    wrapper.between(rangeCondition.getColumn(),
                            rangeCondition.getBegin(),
                            rangeCondition.getEnd());
                } else if (rangeCondition.getBegin() != null) {
                    wrapper.ge(rangeCondition.getColumn(), rangeCondition.getBegin());
                } else if (rangeCondition.getEnd() != null) {
                    wrapper.le(rangeCondition.getColumn(), rangeCondition.getEnd());
                }
            }
        }
        return wrapper;
    }

    public static <T> QueryWrapper<T> getCategories(List<CategoryCondition<?>> categoryConditions, @Nullable QueryWrapper<T> wrapper) {
        wrapper = getWrapper(wrapper);
        if (org.springframework.util.CollectionUtils.isEmpty(categoryConditions)) {
            return wrapper;
        }
        for (CategoryCondition<?> categoryCondition : categoryConditions) {
            if (categoryCondition.getColumn() != null
                    && !org.springframework.util.CollectionUtils.isEmpty(categoryCondition.getCollection())) {
                categoryCondition.camelToUnderline();
                wrapper.in(categoryCondition.getColumn(), categoryCondition.getCollection());
            }
        }
        return wrapper;
    }

    public static <T> QueryWrapper<T> like(T model, @Nullable QueryWrapper<T> wrapper) {
        wrapper = getWrapper(wrapper);
        Map<String, Object> map = BeanUtil.beanToMap(model, true, true);
        if (map == null) {
            return wrapper;
        }
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Boolean ||
                    value instanceof LocalDateTime) {
                wrapper.eq(key, value);
            } else {
                wrapper.like(key, value);
            }
        }
        return wrapper;
    }

    public static <T> QueryWrapper<T> getWrapper(@Nullable QueryWrapper<T> wrapper) {
        if (null == wrapper) {
            wrapper = Wrappers.query();
        }
        return wrapper;
    }

}
